package se.webbzon.oschi01.tools.mapper;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import se.webbzon.oschi01.item.ItemEntry;
import se.webbzon.oschi01.item.ItemEntryMetric;
import se.webbzon.oschi01.item.ItemSet;
import se.webbzon.oschi01.metric.XWangMetric;
import se.webbzon.oschi01.utils.Progress;

public class MapperAutomapper {
	
	private ItemEntryMetric metric;
	
	private double tolerance;
	
	private int searchLimit;
	
	public MapperAutomapper() {
		this(new ItemEntryMetric(new XWangMetric()),0.3,25);
	}
	
	public MapperAutomapper(ItemEntryMetric metric, double tolerance, int searchLimit) {
		this.metric = metric;
		this.tolerance = tolerance;
		this.searchLimit = searchLimit;
	}
	
	public double getTolerance() {
		return tolerance;
	}

	public boolean setTolerance(double tolerance) {
		if (tolerance < 0 || tolerance > 1)
			return false;
		this.tolerance = tolerance;
		return true;
	}

	public ItemEntryMetric getMetric() {
		return metric;
	}

	public void setMetric(ItemEntryMetric metric) {
		this.metric = metric;
	}
	
	public int getSearchLimit() {
		return searchLimit;
	}

	public void setSearchLimit(int searchLimit) {
		this.searchLimit = searchLimit;
	}

	public Progress<Map<ItemEntry,ItemEntry>> automap(final MapperModel model) {
		final double tolerance = this.tolerance;
		final int searchLimit = this.searchLimit;
		final ItemEntryMetric metric = this.metric;
		final Progress<Map<ItemEntry,ItemEntry>> progress = new Progress<Map<ItemEntry,ItemEntry>>();

		Thread thread = new Thread() {
			
			@Override public void run() {
				Map<ItemEntry,ItemEntry> result = new HashMap<ItemEntry,ItemEntry>();
				ItemSet available = model.getAvailableItems();
				Set<ItemEntry> unmapped = model.getUnmappedItems();
				int size = unmapped.size();
				int i = 0;
				for (ItemEntry e : unmapped) {
					Collection<ItemEntry> r = available.similar(e, metric, searchLimit, tolerance);
					if (!r.isEmpty()) {
						result.put(e, r.iterator().next());
					}
					i+=100;
					progress.setProgress(i/size);
				}
				progress.complete(result);
			}
			
			@Override public void interrupt() {
				super.interrupt();
				progress.abort(new InterruptedException());
			}
			
		};
		thread.start();
		return progress;
	}
	
}
